package com.gxar.navigation.server.db.service;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.gxar.common.entity.PageResult;
import com.gxar.common.entity.Result;
import com.gxar.common.exception.APIRuntimeException;
import com.gxar.common.utils.PageUtils;
import com.gxar.common.utils.SnowFlakeUtils;
import com.gxar.navigation.server.base.common.utils.NearestPointLineCalculateUtils;
import com.gxar.navigation.server.base.model.ResultCodeEnum;
import com.gxar.navigation.server.base.model.arithmetic.dto.PointDTO;
import com.gxar.navigation.server.base.model.node.mapper.NodeMapStruct;
import com.gxar.navigation.server.base.model.node.vo.request.DistanceRequest;
import com.gxar.navigation.server.base.model.node.vo.request.NodeCreateRequest;
import com.gxar.navigation.server.base.model.node.vo.request.NodeUpdateRequest;
import com.gxar.navigation.server.base.model.node.vo.response.*;
import com.gxar.navigation.server.db.mapper.NodeMapper;
import com.gxar.navigation.server.db.model.NodeEntity;
import com.gxar.navigation.server.db.repository.NodeRepository;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Objects;
import java.util.Optional;

/**
 * @author linsy
 * @version 1.0
 * @created 2023/9/12 15:07
 */
@Service
@RequiredArgsConstructor
public class NodeService {

    private final NodeMapper nodeMapper;
    private final NodeRepository nodeRepository;

    /**
     * 创建节点
     *
     * @param activeId          活动id
     * @param nodeCreateRequest 创建节点请求
     * @return 响应
     */
    public NodeCreateResponse create(Long activeId, NodeCreateRequest nodeCreateRequest) {
        // 经度
        Double longitude = nodeCreateRequest.getLongitude();
        // 纬度
        Double latitude = nodeCreateRequest.getLatitude();
        NodeEntity nodeEntity = nodeMapper.findByLonAndLat(longitude, latitude);
        if (Objects.nonNull(nodeEntity)) {
            throw new APIRuntimeException(ResultCodeEnum.NODE_EXIST);
        }
        NodeEntity entity = NodeMapStruct.INSTANCE.createRequestToEntity(nodeCreateRequest);
        entity.setActiveId(activeId);
        NodeEntity save = nodeRepository.save(entity);
        return NodeMapStruct.INSTANCE.entityToCreateResponse(save);
    }

    /**
     * 分页查询
     *
     * @param activeId
     * @param pageNum  当前页
     * @param pageSize 页记录数
     * @return 响应
     */
    public Result<PageResult<NodePageResponse>> pageList(Long activeId, Integer pageNum, Integer pageSize) {
        Page<Object> page = PageHelper.startPage(pageNum, pageSize);
        List<NodeEntity> nodeEntities = nodeMapper.queryPage(activeId);
        List<NodePageResponse> nodePageList = NodeMapStruct.INSTANCE.entitiesToPageResponse(nodeEntities);
        PageInfo<NodePageResponse> nodePageInfo = new PageInfo<>(nodePageList);
        nodePageInfo.setTotal(page.getTotal());
        return PageUtils.getPageResult(nodePageInfo, nodePageList);
    }

    /**
     * 获取节点详细信息
     *
     * @param activeId
     * @param id       节点id
     * @return 详细信息
     */
    public NodeInfoResponse getDetail(Long activeId, Long id) {
        Optional<NodeEntity> nodeEntityOptional = nodeRepository.findById(id);
        if (nodeEntityOptional.isPresent()) {
            NodeEntity nodeEntity = nodeEntityOptional.get();
            if (nodeEntity.getActiveId().equals(activeId)) {
                return NodeMapStruct.INSTANCE.entityToInfoResponse(nodeEntity);
            }
        }
        return new NodeInfoResponse();
    }

    /**
     * 更新节点信息
     *
     * @param activeId
     * @param id                节点id
     * @param nodeUpdateRequest 更新信息
     * @return 更新后信息
     */
    public NodeUpdateResponse update(Long activeId, Long id, NodeUpdateRequest nodeUpdateRequest) {
        Optional<NodeEntity> nodeEntity = nodeRepository.findById(id);
        if (!nodeEntity.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.NODE_NOT_EXIST);
        }
        NodeEntity oriNode = nodeEntity.get();
        if (!oriNode.getActiveId().equals(activeId)){
            throw new APIRuntimeException(ResultCodeEnum.NODE_NOT_EXIST);
        }
        NodeEntity entity = NodeMapStruct.INSTANCE.updateRequestToEntity(nodeUpdateRequest);
        entity.setId(oriNode.getId());
        entity.setActiveId(activeId);
        NodeEntity updated = nodeRepository.save(entity);
        return NodeMapStruct.INSTANCE.entityToUpdateResponse(updated);
    }

    /**
     * 删除节点信息
     *
     * @param activeId
     * @param id       节点id
     * @return 是否成功
     */
    public Boolean delete(Long activeId, Long id) {
        Optional<NodeEntity> nodeEntity = nodeRepository.findById(id);
        if (!nodeEntity.isPresent()) {
            throw new APIRuntimeException(ResultCodeEnum.NODE_NOT_EXIST);
        }
        NodeEntity oriNode = nodeEntity.get();
        if (!oriNode.getActiveId().equals(activeId)){
            throw new APIRuntimeException(ResultCodeEnum.NODE_NOT_EXIST);
        }
        nodeRepository.delete(nodeEntity.get());
        return true;
    }

    /**
     * 两点经纬度距离计算
     *
     * @param request 请求
     * @return 响应
     */
    public DistanceResponse distance(DistanceRequest request) {
        double distance = NearestPointLineCalculateUtils.calculateHaversineDistance(
                new PointDTO(Long.parseLong(SnowFlakeUtils.getInstance().nextId()),
                        request.getOrigin().getLatitude(),
                        request.getOrigin().getLongitude()),
                new PointDTO(Long.parseLong(SnowFlakeUtils.getInstance().nextId()),
                        request.getDestination().getLatitude(),
                        request.getDestination().getLongitude()));
        DistanceResponse response = new DistanceResponse();
        response.setDistance(distance);
        return response;
    }
}
